package com.camartsApp.service.impl;

import com.camartsApp.common.PhotoUserVO;
import com.camartsApp.dto.CommentCreateDTO;
import com.camartsApp.dto.CommentDTO;
import com.camartsApp.dto.PostDTO;
import com.camartsApp.mapper.PhotoMapper;
import com.camartsApp.service.PostService;
import com.mongodb.client.result.UpdateResult;
import org.bson.Document;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
public class PostServiceImpl implements PostService {

    @Autowired
    private MongoTemplate mongoTemplate;

    @Autowired
    private PhotoMapper photoMapper;

    @Override
    public PostDTO getPostByImageId(Long imageId) {
        System.out.println("--- [DEBUG] Entering getPostByImageId with imageId: " + imageId + " ---");
        // 1. 根据 imageId 查询帖子信息
        Query postQuery = new Query(Criteria.where("imageId").is(imageId).and("isDelete").is(false));
        Map postMap = mongoTemplate.findOne(postQuery, Map.class, "posts");

        if (postMap == null) {
            System.out.println("--- [DEBUG] Post not found for imageId: " + imageId + " ---");
            return null;
        }

        ObjectId postId = (ObjectId) postMap.get("_id");
        System.out.println("--- [DEBUG] Found post with _id: " + postId.toHexString() + " ---");

        PostDTO postDTO = new PostDTO();
        postDTO.setId(postId.toHexString());

        // --- FIX START ---
        // 将值作为 Number 类型获取，然后再转换为 Long。
        // 这是处理来自 MongoDB 的数字类型的一种更稳健的方法，
        // 因为驱动程序可能会根据值的不同返回 Integer、Long 或 Double。
        Object imageIdObj = postMap.get("imageId");
        if (imageIdObj instanceof Number) {
            postDTO.setImageId(((Number) imageIdObj).longValue());
        } else {
            // 处理值可能为 null 或非数字的情况
            postDTO.setImageId(null);
        }
        // --- FIX END ---

        postDTO.setTitle((String) postMap.get("title"));
        postDTO.setContent((String) postMap.get("content"));

        // 同样地，安全地处理 likeCount
        Object likeCountObj = postMap.get("likeCount");
        if (likeCountObj instanceof Number) {
            postDTO.setLikeCount(((Number) likeCountObj).intValue());
        } else {
            postDTO.setLikeCount(0); // 如果不存在，则默认为 0
        }


        // 2. 根据帖子的 ObjectId 查询所有相关评论
        Criteria orCriteria = new Criteria().orOperator(
                Criteria.where("post_id").is(postId),
                Criteria.where("post_id").is(postId.toHexString())
        );
        Query commentQuery = new Query(new Criteria().andOperator(
                orCriteria,
                Criteria.where("status").in(0, 1)
        ));
        List<Map> commentMaps = mongoTemplate.find(commentQuery, Map.class, "comments");
        System.out.println("--- [DEBUG] Found " + commentMaps.size() + " comments for post. ---");

        if (CollectionUtils.isEmpty(commentMaps)) {
            postDTO.setComments(new ArrayList<>());
            System.out.println("--- [DEBUG] Exiting getPostByImageId (no comments). ---");
            return postDTO;
        }

        // 3. 批量获取评论用户信息
        List<String> userIds = commentMaps.stream()
                .map(commentMap -> String.valueOf(commentMap.get("user_id")))
                .distinct()
                .collect(Collectors.toList());
        System.out.println("--- [DEBUG] Fetching user info for userIds: " + userIds + " ---");

        List<PhotoUserVO> userVOs = photoMapper.findUsersByUserIds(userIds);
        Map<String, PhotoUserVO> userVOMap = userVOs.stream()
                .collect(Collectors.toMap(PhotoUserVO::getUserId, Function.identity()));


        // 4. 构建 CommentDTO 列表
        ArrayList<CommentDTO> commentDTOs = new ArrayList<>();
        for (Map commentMap : commentMaps) {
            CommentDTO commentDTO = new CommentDTO();
            Object commentIdObj = commentMap.get("_id");
            if (commentIdObj instanceof ObjectId) {
                commentDTO.setId(((ObjectId) commentIdObj).toHexString());
            } else {
                commentDTO.setId(String.valueOf(commentIdObj));
            }
            commentDTO.setContent((String) commentMap.get("content"));
            Date createTime = (Date) commentMap.get("create_time");
            if (createTime != null) {
                commentDTO.setCreateTime(createTime.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime());
            }
            String userId = String.valueOf(commentMap.get("user_id"));
            commentDTO.setUserId(userId);
            PhotoUserVO userVO = userVOMap.get(userId);
            if (userVO != null) {
                commentDTO.setAvatar(userVO.getAvatar());
                commentDTO.setNickname(userVO.getNickname());
            }
            commentDTOs.add(commentDTO);
        }

        postDTO.setComments(commentDTOs);
        System.out.println("--- [DEBUG] Exiting getPostByImageId successfully. ---");
        return postDTO;
    }

    @Override
    public boolean addComment(CommentCreateDTO commentCreateDTO) {
        System.out.println("--- [DEBUG] Entering addComment ---");
        System.out.println("--- [DEBUG] Request Body: " + commentCreateDTO.toString() + " ---");

        if (!StringUtils.hasText(commentCreateDTO.getPostId()) || commentCreateDTO.getUserId() == null) {
            throw new IllegalArgumentException("Post ID and User ID cannot be null.");
        }

        Document commentDoc = new Document();
        commentDoc.put("post_id", new ObjectId(commentCreateDTO.getPostId()));
        commentDoc.put("user_id", commentCreateDTO.getUserId());
        commentDoc.put("content", commentCreateDTO.getContent());
        commentDoc.put("create_time", new Date());
        commentDoc.put("like_count", 0);
        commentDoc.put("status", 1);

        mongoTemplate.insert(commentDoc, "comments");
        System.out.println("--- [DEBUG] Comment inserted successfully. ---");
        return true;
    }

    @Override
    public boolean reportComment(String commentId) {
        System.out.println("--- [DEBUG] Entering reportComment with commentId: " + commentId + " ---");

        if (!ObjectId.isValid(commentId)) {
            System.out.println("--- [DEBUG] Invalid ObjectId format for commentId: " + commentId + " ---");
            return false;
        }

        Query query = new Query(Criteria.where("_id").is(new ObjectId(commentId)));
        Map comment = mongoTemplate.findOne(query, Map.class, "comments");

        if (comment == null) {
            System.out.println("--- [DEBUG] Comment not found for commentId: " + commentId + " ---");
            return false;
        }

        Object statusObj = comment.get("status");
        int currentStatus = -1;
        if (statusObj instanceof Integer) {
            currentStatus = (Integer) statusObj;
        }

        System.out.println("--- [DEBUG] Current status of comment " + commentId + " is: " + currentStatus + " ---");

        if (currentStatus == 0) {
            System.out.println("--- [DEBUG] Comment status is already 0. Reporting is considered successful. ---");
            return true;
        } else {
            Update update = new Update().set("status", 0);
            UpdateResult result = mongoTemplate.updateFirst(query, update, "comments");
            System.out.println("--- [DEBUG] Updating status to 0. Modified count: " + result.getModifiedCount() + " ---");
            return true;
        }
    }

    @Override
    public boolean reportPost(Long imageId) {
        System.out.println("--- [DEBUG] Entering reportPost with imageId: " + imageId + " ---");
        Integer affectedRows = photoMapper.updatePhotoStatus(imageId, 0);
        System.out.println("--- [DEBUG] Report post result - Affected rows: " + affectedRows + " ---");
        return affectedRows != null && affectedRows > 0;
    }
}
